// 简单工厂模式（共用体继承）-以水果店为例
// 共用体中多个变量使用一块内存空间，因此在共用体中罗列出不同的结构体可以实现继承的关系
// 例如水果抽象类可以用一个结构体表示，而其中的子类即具体的水果类型可以在里面放一个共用体，并在共用体中罗列出全部类型具体水果
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

/// @brief 表示口味类型的字符串常量（作为参数）
static char SWEET[] = "SWEET", ACID[] = "ACID", SWEET_ACID[] = "SWEET_ACID";

/// @brief 表示水果类型的抽象类结构体，里面包含一个共用体表示一类水果
typedef struct
{
	char name[16]; // 水果名（父类属性）
	union
	{
		/// @brief 子类：苹果
		struct
		{
			int sweetness; // 甜度
		} apple;
		/// @brief 子类：橙子
		struct
		{
			int acidity; // 酸度
		} orange;
		/// @brief 子类：西瓜
		struct
		{
			int cooked; // 是否保熟
		} watermelon;
	} content; // 这个共用体表示子类
} Fruit;

/// @brief 工厂模式：水果工厂方法
/// @param flavor 客户口味参数
/// @return 对应的水果
Fruit *fruitFactoryGet(char flavor[])
{
	// 生成的水果
	Fruit *fruit = (Fruit *)malloc(sizeof(Fruit));
	// 客户口味为酸甜，生成苹果
	if (strcmp(flavor, SWEET_ACID) == 0)
	{
		strcpy(fruit->name, "苹果");
		fruit->content.apple.sweetness = 3;
	}
	else if (strcmp(flavor, ACID) == 0)
	{
		// 客户口味为酸，生成橙子
		strcpy(fruit->name, "橙子");
		fruit->content.orange.acidity = 100;
	}
	else if (strcmp(flavor, SWEET) == 0)
	{
		// 客户口味为甜，生成西瓜
		strcpy(fruit->name, "西瓜");
		fruit->content.watermelon.cooked = 1;
	}
}

int main()
{
	printf("有一个人前来买瓜...\n");
	Fruit *watermelon = fruitFactoryGet(SWEET);
	printf("客户买到了：%s，这瓜保熟吗？%s\n", watermelon->name, watermelon->content.watermelon.cooked ? "保熟！" : "不保熟！");
	return 0;
}